package gitee

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"strconv"

	"gitee.com/StarCitizen_CN/logger"
	"gitee.com/StarCitizen_CN/stargox/pkg/codes"
)

type DownloadCB func(total, complete int)
type DownloadCounter struct {
	Total, Completed int
	callback         DownloadCB
}

func (dc *DownloadCounter) Write(p []byte) (int, error) {
	n := len(p)
	dc.Completed += n

	if dc.callback != nil {
		dc.callback(dc.Total, dc.Completed)
	}

	return n, nil
}

func Get(url string) (data []byte, err error) {
	r, callErr := http.Get(url)
	if callErr != nil {
		err = fmt.Errorf(codes.ErrNetReq, callErr)
		return nil, callErr
	}
	defer r.Body.Close()

	data, readErr := io.ReadAll(r.Body)
	if readErr != nil {
		err = fmt.Errorf(codes.ErrNetRead, readErr)
		return nil, err
	}

	return data, nil
}

func Download(url, filePath string, cb DownloadCB) error {

	// 先清理现场
	if rmErr := os.Remove(filePath); rmErr != nil {
		if !os.IsNotExist(rmErr) {
			return rmErr
		}
	}

	output, err := os.Create(filePath)
	if err != nil {
		return err
	}
	defer output.Close()

	resp, callErr := http.Get(url)
	if callErr != nil {
		return callErr
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("error http code %d: %s", resp.StatusCode, url)
	}

	size, _ := strconv.Atoi(resp.Header.Get("Content-Length"))
	downloadSize := size
	logger.Var("%s downloadSize %d", url, downloadSize)

	dc := DownloadCounter{
		Total:    downloadSize,
		callback: cb,
	}
	completedN, ioCpErr := io.Copy(output, io.TeeReader(resp.Body, &dc))
	if err != nil {
		return ioCpErr
	}

	// 仅仅输出日志
	// 默认已下载完成
	if completedN != int64(downloadSize) {
		logger.Err(fmt.Errorf("download completed: %d/%d", completedN, downloadSize))
	}

	return nil
}
